package com.jichangxiu.server.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jichangxiu.common.annotation.DataScope;
import com.jichangxiu.common.constant.Constant;
import com.jichangxiu.common.entity.bo.PageData;
import com.jichangxiu.common.entity.bo.Record;
import com.jichangxiu.common.exception.ServiceException;
import com.jichangxiu.common.utils.StrUtils;
import com.jichangxiu.common.utils.TokenUtils;
import com.jichangxiu.framework.mybatis.BaseServiceImpl;
import com.jichangxiu.server.platform.entity.dto.PlatformDeptQueryDto;
import com.jichangxiu.server.platform.entity.map.PlatformDeptBasic;
import com.jichangxiu.server.platform.entity.po.PlatformDept;
import com.jichangxiu.server.platform.entity.po.PlatformDeptRole;
import com.jichangxiu.server.platform.entity.po.PlatformPost;
import com.jichangxiu.server.platform.entity.po.PlatformUser;
import com.jichangxiu.server.platform.entity.vo.PlatformDeptAddVo;
import com.jichangxiu.server.platform.entity.vo.PlatformDeptEditVo;
import com.jichangxiu.server.platform.entity.vo.PlatformDeptQueryVo;
import com.jichangxiu.server.platform.mapper.PlatformDeptMapper;
import com.jichangxiu.server.platform.service.PlatformDeptRoleService;
import com.jichangxiu.server.platform.service.PlatformDeptService;
import com.jichangxiu.server.platform.service.PlatformPostService;
import com.jichangxiu.server.platform.service.PlatformUserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;

/**
 * PlatformDeptServiceImpl:
 *
 * @author Jcx
 * @create 2023-03-08 21:17
 */
@Service
public class PlatformDeptServiceImpl extends BaseServiceImpl<PlatformDeptMapper, PlatformDept> implements PlatformDeptService {

    @Resource
    private TokenUtils tokenUtils;

    @Resource
    private StrUtils strUtils;

    @Resource
    private PlatformDeptMapper platformDeptMapper;

    @Resource
    private PlatformDeptRoleService platformDeptRoleService;

    @Resource
    private PlatformUserService platformUserService;

    @Resource
    private PlatformPostService platformPostService;

    /**
     * 新增部门
     *
     * @param platformDeptAddVo 部门视图对象
     * @return 是否成功
     */
    @Override
    public Boolean add(PlatformDeptAddVo platformDeptAddVo) {
        if (ObjectUtil.isEmpty(platformDeptAddVo)) {
            throw ServiceException.build("部门对象无效");
        }

        PlatformDept platformDept = PlatformDeptBasic.INSTANCE.toPlatformDept(platformDeptAddVo);
        if (ObjectUtil.isEmpty(platformDept)) {
            throw ServiceException.build("部门对象无效");
        }

        if (!Validator.isEmail(platformDept.getEmail())) {
            throw ServiceException.build("部门联系邮箱不符合规范");
        }

        if (!Validator.isMobile(platformDept.getPhone())) {
            throw ServiceException.build("部门联系电话不符合规范");
        }

        if (Constant.PLATFORM_SUPER_DEPT.equals(platformDept.getDeptCode())) {
            throw ServiceException.build("部门标识不能为 PLATFORM_SUPER_DEPT");
        }

        if (Constant.SYSTEM_SUPER_DEPT.equals(platformDept.getDeptCode())) {
            throw ServiceException.build("部门标识不能为 SYSTEM_SUPER_DEPT");
        }

        // Code 必须唯一
        PlatformDept dbPlatformDeptByCode = getOne(new LambdaQueryWrapper<PlatformDept>().eq(PlatformDept::getDeptCode, platformDept.getDeptCode()));
        if (ObjectUtil.isNotEmpty(dbPlatformDeptByCode)) {
            throw ServiceException.build(platformDept.getDeptName() + "该部门的标识重复");
        }

        // name 必须唯一
        PlatformDept dbPlatformDeptByName = getOne(new LambdaQueryWrapper<PlatformDept>().eq(PlatformDept::getDeptName, platformDept.getDeptName()));
        if (ObjectUtil.isNotEmpty(dbPlatformDeptByName)) {
            throw ServiceException.build(platformDept.getDeptName() + "该部门的名称重复");
        }

        if (StrUtil.isBlank(platformDept.getParentId())) {
            platformDept.setParentId("0");
        }
        platformDept.setDeptNo(strUtils.createNo("dept"));
        platformDept.setTenantId(tokenUtils.getTenantId());
        return save(platformDept);
    }

    /**
     * 多选级联删除部门
     *
     * @param deptIdList 部门ID列表
     * @return 是否成功
     */
    @Override
    public Boolean del(List<String> deptIdList) {
        List<PlatformDept> platformDeptList = list(new LambdaQueryWrapper<PlatformDept>().in(PlatformDept::getDeptId, deptIdList));
        if (ObjectUtil.isEmpty(platformDeptList)) {
            throw ServiceException.build("数据库中不存在需要删除的记录");
        }

        platformDeptList.forEach(platformDept -> {
            if (Constant.PLATFORM_SUPER_DEPT.equals(platformDept.getDeptCode())) {
                throw ServiceException.build("标识为 PLATFORM_SUPER_DEPT 的部门不能删除");
            }

            if (Constant.SYSTEM_SUPER_DEPT.equals(platformDept.getDeptCode())) {
                throw ServiceException.build("标识为 SYSTEM_SUPER_DEPT 的部门不能删除");
            }
        });

        // 填充子部门
        List<PlatformDept> allSubPlatformDeptList = list(new LambdaQueryWrapper<PlatformDept>().in(PlatformDept::getParentId, deptIdList));
        platformDeptList.forEach(platformDept -> {
            List<PlatformDept> subPlatformDeptList = new ArrayList<>();
            if (ObjectUtil.isNotEmpty(allSubPlatformDeptList)) {
                allSubPlatformDeptList.forEach(subPlatformDept -> {
                    if (platformDept.getDeptId().equals(subPlatformDept.getParentId())) {
                        subPlatformDeptList.add(subPlatformDept);
                    }
                });
            }
            platformDept.setSubPlatformDepts(subPlatformDeptList);
        });
        // 根据部门ID列表查询对应的用户列表
        List<PlatformUser> platformUserList = platformUserService.list(new LambdaQueryWrapper<PlatformUser>().in(PlatformUser::getDeptId, deptIdList));
        platformDeptList.forEach(platformDept -> {
            // 将部门和用户对应起来，这里的对应关系是：一个部门对应多个用户
            List<PlatformUser> platformUsers = new ArrayList<>();
            if (ObjectUtil.isNotEmpty(platformUserList)) {
                platformUserList.forEach(platformUser -> {
                    if (platformDept.getDeptId().equals(platformUser.getDeptId())) {
                        platformUsers.add(platformUser);
                    }
                });
            }
            platformDept.setPlatformUsers(platformUsers);
        });

        // 根据部门ID列表查询对应的岗位列表
        List<PlatformPost> platformPostList = platformPostService.list(new LambdaQueryWrapper<PlatformPost>().in(PlatformPost::getDeptId, deptIdList));
        platformDeptList.forEach(platformDept -> {
            // 将部门和岗位对应起来，这里的对应关系是：一个部门对应多个岗位
            List<PlatformPost> platformPosts = new ArrayList<>();
            if (ObjectUtil.isNotEmpty(platformUserList)) {
                platformPostList.forEach(platformPost -> {
                    if (platformDept.getDeptId().equals(platformPost.getDeptId())) {
                        platformPosts.add(platformPost);
                    }
                });
            }
            platformDept.setPlatformPosts(platformPosts);
        });

        platformDeptList.forEach(platformDept -> {
            // 校验部门下有子部门不能删除
            // 如果某个部门下还存在子部门，则部门不能删除
            List<PlatformDept> subPlatformDeptList = platformDept.getSubPlatformDepts();
            if (ObjectUtil.isNotEmpty(subPlatformDeptList)) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门下还存在子部门，不能删除");
            }
            // 校验部门下有用户不能删除
            // 如果某个部门下还存在用户，则部门不能删除
            List<PlatformUser> platformUsers = platformDept.getPlatformUsers();
            if (ObjectUtil.isNotEmpty(platformUsers)) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门下还存在用户，不能删除");
            }
            // 校验部门下有用户不能删除
            // 如果某个部门下还存在用户，则部门不能删除
            List<PlatformPost> platformPosts = platformDept.getPlatformPosts();
            if (ObjectUtil.isNotEmpty(platformPosts)) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门下还存在岗位，不能删除");
            }
        });

        // 删除部门
        boolean b1 = removeBatchByIds(deptIdList);
        // 删除部门角色关联关系
        // 默认是成功状态
        boolean b2 = true;
        List<PlatformDeptRole> platformDeptRoleList = platformDeptRoleService.list(new LambdaQueryWrapper<PlatformDeptRole>().in(PlatformDeptRole::getDeptId, deptIdList));
        if (ObjectUtil.isNotEmpty(platformDeptRoleList)) {
            List<String> idList = new ArrayList<>();
            platformDeptRoleList.forEach(platformDeptRole -> idList.add(platformDeptRole.getId()));
            if (ObjectUtil.isNotEmpty(idList)) {
                b2 = platformDeptRoleService.removeBatchByIds(idList);
            }
        }
        return b1 && b2;
    }

    /**
     * 修改部门信息
     *
     * @param platformDeptEditVo 部门视图对象
     * @return 是否成功
     */
    @Override
    public Boolean edit(PlatformDeptEditVo platformDeptEditVo) {
        if (ObjectUtil.isEmpty(platformDeptEditVo)) {
            throw ServiceException.build("部门对象无效");
        }

        PlatformDept platformDept = PlatformDeptBasic.INSTANCE.toPlatformDept(platformDeptEditVo);

        if (ObjectUtil.isEmpty(platformDept)) {
            throw ServiceException.build("部门对象无效");
        }

        PlatformDept dbPlatformDept = getOne(new LambdaQueryWrapper<PlatformDept>().eq(PlatformDept::getDeptId, platformDept.getDeptId()));
        if (ObjectUtil.isEmpty(dbPlatformDept)) {
            throw ServiceException.build(platformDept.getDeptName() + "该部门在数据库中不存在");
        }

        if (!Validator.isEmail(platformDept.getEmail())) {
            throw ServiceException.build("部门联系邮箱不符合规范");
        }

        if (!Validator.isMobile(platformDept.getPhone())) {
            throw ServiceException.build("部门联系电话不符合规范");
        }

        if (Constant.PLATFORM_SUPER_DEPT.equals(dbPlatformDept.getDeptCode()) && !dbPlatformDept.getDeptCode().equals(platformDept.getDeptCode())) {
            throw ServiceException.build("标识为 PLATFORM_SUPER_DEPT 的部门标识不能修改");
        }

        if (Constant.PLATFORM_SUPER_DEPT.equals(dbPlatformDept.getDeptCode()) && !dbPlatformDept.getStatus().equals(platformDept.getStatus())) {
            throw ServiceException.build("标识为 PLATFORM_SUPER_DEPT 的部门状态不能修改");
        }

        if (Constant.SYSTEM_SUPER_DEPT.equals(dbPlatformDept.getDeptCode()) && !dbPlatformDept.getDeptCode().equals(platformDept.getDeptCode())) {
            throw ServiceException.build("标识为 SYSTEM_SUPER_DEPT 的部门标识不能修改");
        }

        if (Constant.SYSTEM_SUPER_DEPT.equals(dbPlatformDept.getDeptCode()) && !dbPlatformDept.getStatus().equals(platformDept.getStatus())) {
            throw ServiceException.build("标识为 SYSTEM_SUPER_DEPT 的部门状态不能修改");
        }

        // Code 必须唯一
        if (!platformDept.getDeptCode().equals(dbPlatformDept.getDeptCode())) {
            PlatformDept dbPlatformDeptByCode = getOne(new LambdaQueryWrapper<PlatformDept>().eq(PlatformDept::getDeptCode, platformDept.getDeptCode()));
            if (ObjectUtil.isNotEmpty(dbPlatformDeptByCode)) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门的标识重复");
            }
        }

        // name 必须唯一
        if (!platformDept.getDeptName().equals(dbPlatformDept.getDeptName())) {
            PlatformDept dbPlatformDeptByName = getOne(new LambdaQueryWrapper<PlatformDept>().eq(PlatformDept::getDeptName, platformDept.getDeptName()));
            if (ObjectUtil.isNotEmpty(dbPlatformDeptByName)) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门的名称重复");
            }
        }

        // 修改了状态的话，如果有子部门不能修改
        if (!platformDept.getStatus().equals(dbPlatformDept.getStatus()) && !platformDept.getStatus()) {
            // 填充子部门
            List<PlatformDept> allSubPlatformDeptList = list(new LambdaQueryWrapper<PlatformDept>().in(PlatformDept::getParentId, platformDept.getDeptId()));
            // 校验部门下有子部门不能修改
            if (ObjectUtil.isNotEmpty(allSubPlatformDeptList)) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门下还存在子部门，不能修改状态为禁用");
            }
            // 如果被用户关联不能修改
            List<PlatformUser> platformUserList = platformUserService.list(new LambdaQueryWrapper<PlatformUser>().in(PlatformUser::getDeptId, platformDept.getDeptId()));
            if (ObjectUtil.isNotEmpty(platformUserList)) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门已被用户关联，不能修改状态为禁用");
            }
            // 如果被岗位关联不能修改
            List<PlatformPost> platformPostList = platformPostService.list(new LambdaQueryWrapper<PlatformPost>().in(PlatformPost::getDeptId, platformDept.getDeptId()));
            if (ObjectUtil.isNotEmpty(platformPostList)) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门已被岗位关联，不能修改状态为禁用");
            }
        }

        if (StrUtil.isBlank(platformDept.getParentId())) {
            platformDept.setParentId("0");
        }

        // 父类 不能是自己
        if (!platformDept.getParentId().equals(dbPlatformDept.getParentId())) {
            if (platformDept.getParentId().equals(dbPlatformDept.getDeptId())) {
                throw ServiceException.build(platformDept.getDeptName() + "该部门的父部门不能是自己");
            }
        }
        BeanUtil.copyProperties(platformDept, dbPlatformDept, true);
        return updateById(dbPlatformDept);
    }

    /**
     * 根据ID获取树形部门详情
     *
     * @param deptId 部门ID
     * @return 树形部门详情
     */
    @Override
    public Record info(@NotBlank(message = "部门ID不能为空") String deptId) {
        Page<PlatformDept> page = startPage();
        List<PlatformDept> platformDeptList = platformDeptMapper.pageList(PlatformDept.builder().deptId(deptId).tenantId(tokenUtils.getTenantId()).build(), page);
        if (ObjectUtil.isEmpty(platformDeptList) || platformDeptList.size() != 1) {
            throw ServiceException.build(deptId + "此数据在数据库中不存在或存在多条");
        }
        return Record.getRecordByModel(PlatformDeptBasic.INSTANCE.toPlatformDeptQueryDto(platformDeptList.get(0)));
    }

    /**
     * 分页查询树形部门列表
     *
     * @param platformDeptQueryVo 部门视图对象
     * @return 分页树形部门列表
     */
    @Override
    @DataScope
    public PageData<Record> pageList(PlatformDeptQueryVo platformDeptQueryVo) {
        Page<PlatformDept> page = startPage();
        // 执行数据库查询
        List<PlatformDept> platformDeptList = platformDeptMapper.pageList(PlatformDeptBasic.INSTANCE.toPlatformDept(platformDeptQueryVo), page);

        if (ObjectUtil.isEmpty(platformDeptList)) {
            return PageData.build(new Page<>(page.getCurrent(), page.getSize(), page.getTotal()), new ArrayList<>());
        }

        List<PlatformDeptQueryDto> platformDeptQueryDtoList = PlatformDeptBasic.INSTANCE.toPlatformDeptQueryDtoList(platformDeptList);

        // 填充 创建时间
        List<Record> recordList = Record.getRecordByList(platformDeptQueryDtoList);
        recordList.forEach(record -> {
            platformDeptQueryDtoList.forEach(platformDeptQueryDto -> {
                if (platformDeptQueryDto.getDeptId().equals(record.getStr("deptId"))) {
                    record.set("createTime", DateUtil.formatDateTime(platformDeptQueryDto.getCreateTime()));
                }
            });
        });

        // 转换为 tree
        List<Record> treeRecordList = Record.listToTree(recordList, "deptId", "parentId", "children");
        return PageData.build(new Page<Record>(page.getCurrent(), page.getSize(), page.getTotal()), treeRecordList);
    }

}
